package com.kaifamiao.sync;

/**
 * 1、若同步方法是实例方法，则该方法以 当前实例(this) 为 监视器
 * 2、若同步方法是类方法，则该方法以 该类对应的Class实例 为 监视器
 */
public class IcbcAccount {

    private String name; // 开户名称
    private long balance; // 账户余额
    private long threshold; // 阈值(少于这个数就要存款了)

    public IcbcAccount(String name, long balance, long threshold) {
        this.name = name;
        if( balance > 0 ) {
            this.balance = balance;
        }
        if( threshold > 0 ) {
            this.threshold = threshold;
        }
    }

    /**
     * 向账户存款
     *   这是个同步方法，它以 当前实例(this) 为 监视器
     * @param amount 存款金额
     */
    public synchronized void deposit(long amount) {
        String threadName = Thread.currentThread().getName();
        if ( this.balance < this.threshold ) {
            System.out.printf("当前余额为: %d元，%s开始存款\n", this.balance, threadName );
            this.balance += amount; // 存款
            System.out.printf("%s存款结束，当前余额为: %d\n", threadName, this.balance);
            return;
        }
        System.out.printf("账上钱够用，%s不必存款\n", threadName);
    }

    /**
     * 取款方法
     *    虽然这个方法不是同步方法，但是其内部的所有代码都在同步代码块中
     * @param amount 取款金额
     */
    public void withdraw(long amount) {
        // 以 当前实例(this) 为 监视器
        synchronized ( this ) { // `monitorenter`
            String threadName = Thread.currentThread().getName();
            if ( balance >= amount ) {
                System.out.printf("当前余额为: %d元，%s开始取款\n", balance, threadName );
                balance -= amount; // 取款
                System.out.printf("%s取款结束，当前余额为: %d\n", threadName, balance);
                return;
            }
            System.out.printf("余额不足，%s取钱失败\n", threadName);
        } // `monitorexit`
    }

}
